package com.xdb.logging;

import java.lang.reflect.Constructor;

/**
 * 日志工厂<br>
 * 日志自动识别已经装载的日志实现返回日志对象<br>
 * 顺序如下:<br>
 * <ol>
 * <li>log4j</li>
 * <li>JDK</li>
 * <li>NOP</li>
 * </ol>
 * 
 * @author woate
 *
 */
@SuppressWarnings("rawtypes")
public class LogFactory {

	private static final String JAVA_UTIL_LOGGING_LOGGER = "java.util.logging.Logger";
	private static final String ORG_APACHE_LOG4J_LOGGER = "org.apache.log4j.Logger";
	private static final String COM_XDB_LOGGING_JDK14_LOG_IMPL = "com.xdb.logging.Jdk14LogImpl";
	private static final String COM_XDB_LOGGING_LOG4J_IMPL = "com.xdb.logging.Log4jImpl";
	static Constructor logConstructor;

	static {
//		tryImplementation(JAVA_UTIL_LOGGING_LOGGER, COM_XDB_LOGGING_JDK14_LOG_IMPL);
//		tryImplementation(ORG_APACHE_LOG4J_LOGGER, COM_XDB_LOGGING_LOG4J_IMPL);

		if (logConstructor == null) {
			try {
				logConstructor = NOPLoggerImpl.class.getConstructor(String.class);
			} catch (Exception e) {
				throw new IllegalStateException(e.getMessage(), e);
			}
		}
	}

	/**
	 * 尝试加载日志具体实现，如果发现已经有构造器则直接返回，否则进行加载
	 * 
	 * @param testClassName
	 *            日志全限定名
	 * @param implClassName
	 *            XDB中的包装类
	 */
	@SuppressWarnings("unchecked")
	static void tryImplementation(String testClassName, String implClassName) {
		// 如果已经初始化，则直接返回
		if (logConstructor != null) {
			return;
		}

		try {
			Resources.classForName(testClassName);
			Class implClass = Resources.classForName(implClassName);
			logConstructor = implClass.getConstructor(new Class[] { String.class });

			Class<?> declareClass = logConstructor.getDeclaringClass();
			if (!Logger.class.isAssignableFrom(declareClass)) {
				logConstructor = null;
			}

			try {
				if (null != logConstructor) {
					logConstructor.newInstance(LogFactory.class.getName());
				}
			} catch (Throwable t) {
				logConstructor = null;
			}

		} catch (Throwable t) {
			// skip
		}
	}

	/**
	 * 获取日志对象
	 * 
	 * @param clazz
	 *            日志对象名称
	 */
	public static Logger getLog(Class clazz) {
		return getLog(clazz.getName());
	}

	/**
	 * 获取日志对象
	 * 
	 * @param name
	 *            日志对象名称
	 * @return 日志对象
	 */
	public static Logger getLog(String name) {
		try {
			return (Logger) logConstructor.newInstance(name);
		} catch (Throwable t) {
			throw new RuntimeException("Error creating logger for logger '" + name + "'.  Cause: " + t, t);
		}
	}

	/**
	 * 设置为Log4j作为日志输出
	 */
	@SuppressWarnings("unchecked")
	public static synchronized void setLog4j() {
		try {
			Resources.classForName(ORG_APACHE_LOG4J_LOGGER);
			Class implClass = Resources.classForName(COM_XDB_LOGGING_LOG4J_IMPL);
			logConstructor = implClass.getConstructor(new Class[] { String.class });
		} catch (Throwable t) {
			// ignore
		}
	}

	/**
	 * 设置为JDK自带日志作为日志输出
	 */
	@SuppressWarnings("unchecked")
	public static synchronized void setJdk14Log() {
		try {
			Resources.classForName(JAVA_UTIL_LOGGING_LOGGER);
			Class implClass = Resources.classForName(COM_XDB_LOGGING_JDK14_LOG_IMPL);
			logConstructor = implClass.getConstructor(new Class[] { String.class });
		} catch (Throwable t) {
			// ignore
		}
	}
	/**
	 * 设置为System.out和System.err作为日志输出
	 */
	public static synchronized void setNOPLog() {
		try {
			logConstructor = NOPLoggerImpl.class.getConstructor(String.class);
		} catch (Throwable t) {
			// ignore
		}
	}
}
